using System;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SeataNet.Core.Attributes;
using SeataNet.Core.Common;
using SeataNet.Core.Context;
using SeataNet.Core.Model;

namespace SeataNet.Core.XA
{
    /// <summary>
    /// XA事务拦截器，处理XA模式的事务拦截
    /// </summary>
    public class XaTransactionInterceptor : IInterceptor
    {
        private readonly ILogger<XaTransactionInterceptor> _logger;
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="serviceProvider">服务提供者</param>
        public XaTransactionInterceptor(ILogger<XaTransactionInterceptor> logger, IServiceProvider serviceProvider)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
        }

        /// <summary>
        /// 拦截方法调用
        /// </summary>
        /// <param name="invocation">方法调用上下文</param>
        public void Intercept(IInvocation invocation)
        {
            // 获取方法上的GlobalTransactionalAttribute
            var method = invocation.Method;
            var attribute = method.GetCustomAttribute<GlobalTransactionalAttribute>();
            
            if (attribute == null)
            {
                // 如果没有事务注解，直接执行方法
                invocation.Proceed();
                return;
            }

            // 获取XA事务管理器
            var xaTransactionManager = _serviceProvider.GetRequiredService<IXaTransactionManager>();
            
            // 执行XA事务
            ExecuteWithXaTransaction(invocation, xaTransactionManager, attribute).GetAwaiter().GetResult();
        }

        /// <summary>
        /// 执行XA事务
        /// </summary>
        /// <param name="invocation">方法调用上下文</param>
        /// <param name="xaTransactionManager">XA事务管理器</param>
        /// <param name="attribute">事务属性</param>
        /// <returns>任务</returns>
        private async Task ExecuteWithXaTransaction(
            IInvocation invocation, 
            IXaTransactionManager xaTransactionManager, 
            GlobalTransactionalAttribute attribute)
        {
            var methodName = invocation.Method.Name;
            var className = invocation.TargetType.Name;
            
            _logger.LogInformation("开始执行XA事务: {className}.{methodName}", className, methodName);
            
            // 检查是否已经有全局事务
            var xid = RootContext.GetXid();
            if (!string.IsNullOrEmpty(xid))
            {
                // 已有全局事务，直接执行方法
                _logger.LogInformation("已存在全局事务，直接执行方法: xid={xid}", xid);
                invocation.Proceed();
                return;
            }

            GlobalTransactionContext transactionContext = null;
            try
            {
                // 开始XA全局事务
                xid = await xaTransactionManager.BeginAsync(attribute.TimeoutMilliseconds);

                _logger.LogInformation("XA全局事务已开始: xid={xid}", xid);
                
                // 绑定XID到上下文
                RootContext.Bind(xid);
                
                // 执行方法
                invocation.Proceed();
                
                // 获取方法返回值
                var result = invocation.ReturnValue;
                
                // 如果方法是异步的，等待结果
                if (result is Task task)
                {
                    await task;
                    
                    // 获取异步结果
                    var resultProperty = task.GetType().GetProperty("Result");
                    if (resultProperty != null)
                    {
                        result = resultProperty.GetValue(task);
                    }
                }
                
                // 提交XA事务
                var commitResult = await xaTransactionManager.CommitAsync(xid);
                
                if (commitResult)
                {
                    _logger.LogInformation("XA全局事务已提交: xid={xid}", xid);
                }
                else
                {
                    _logger.LogWarning("XA全局事务提交失败: xid={xid}", xid);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "XA事务执行异常: xid={xid}", xid);
                
                if (!string.IsNullOrEmpty(xid))
                {
                    try
                    {
                        // 回滚XA事务
                        var rollbackResult = await xaTransactionManager.RollbackAsync(xid);
                        
                        if (rollbackResult)
                        {
                            _logger.LogInformation("XA全局事务已回滚: xid={xid}", xid);
                        }
                        else
                        {
                            _logger.LogWarning("XA全局事务回滚失败: xid={xid}", xid);
                        }
                    }
                    catch (Exception rollbackEx)
                    {
                        _logger.LogError(rollbackEx, "XA事务回滚异常: xid={xid}", xid);
                    }
                }
                
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }
    }

    /// <summary>
    /// XA事务切面类，提供声明式事务支持
    /// </summary>
    public class XaTransactionAspect
    {
        private readonly ILogger<XaTransactionAspect> _logger;
        private readonly IXaTransactionManager _xaTransactionManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="xaTransactionManager">XA事务管理器</param>
        public XaTransactionAspect(
            ILogger<XaTransactionAspect> logger,
            IXaTransactionManager xaTransactionManager)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _xaTransactionManager = xaTransactionManager ?? throw new ArgumentNullException(nameof(xaTransactionManager));
        }

        /// <summary>
        /// 在方法执行前处理
        /// </summary>
        /// <param name="attribute">事务属性</param>
        /// <returns>事务上下文</returns>
        public async Task<GlobalTransactionContext> OnEntryAsync(GlobalTransactionalAttribute attribute)
        {
            _logger.LogInformation("XA事务切面进入");
            
            // 检查是否已经有全局事务
            var xid = RootContext.GetXid();
            if (!string.IsNullOrEmpty(xid))
            {
                _logger.LogInformation("已存在全局事务，跳过XA事务开始: xid={xid}", xid);
                return null;
            }

            // 开始XA全局事务
            xid = await _xaTransactionManager.BeginAsync(attribute.TimeoutMilliseconds);

            _logger.LogInformation("XA全局事务已开始: xid={xid}", xid);

            // 绑定XID到上下文
            RootContext.Bind(xid);

            // 创建事务上下文
            var transactionContext = new GlobalTransactionContext
            {
                Xid = xid,
                Status = 0, // Begin
                BeginTime = DateTime.UtcNow,
                Timeout = attribute.TimeoutMilliseconds
            };

            return transactionContext;
        }

        /// <summary>
        /// 在方法执行成功后处理
        /// </summary>
        /// <param name="transactionContext">事务上下文</param>
        /// <returns>任务</returns>
        public async Task OnSuccessAsync(GlobalTransactionContext transactionContext)
        {
            if (transactionContext == null)
            {
                return;
            }

            var xid = transactionContext.Xid;
            _logger.LogInformation("XA事务切面成功: xid={xid}", xid);
            
            try
            {
                // 提交XA事务
                var commitResult = await _xaTransactionManager.CommitAsync(xid);
                
                if (commitResult)
                {
                    _logger.LogInformation("XA全局事务已提交: xid={xid}", xid);
                }
                else
                {
                    _logger.LogWarning("XA全局事务提交失败: xid={xid}", xid);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "XA事务提交异常: xid={xid}", xid);
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }

        /// <summary>
        /// 在方法执行异常后处理
        /// </summary>
        /// <param name="transactionContext">事务上下文</param>
        /// <param name="exception">异常</param>
        /// <returns>任务</returns>
        public async Task OnExceptionAsync(GlobalTransactionContext transactionContext, Exception exception)
        {
            if (transactionContext == null)
            {
                return;
            }

            var xid = transactionContext.Xid;
            _logger.LogError(exception, "XA事务切面异常: xid={xid}", xid);
            
            try
            {
                // 回滚XA事务
                var rollbackResult = await _xaTransactionManager.RollbackAsync(xid);
                
                if (rollbackResult)
                {
                    _logger.LogInformation("XA全局事务已回滚: xid={xid}", xid);
                }
                else
                {
                    _logger.LogWarning("XA全局事务回滚失败: xid={xid}", xid);
                }
            }
            catch (Exception rollbackEx)
            {
                _logger.LogError(rollbackEx, "XA事务回滚异常: xid={xid}", xid);
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }
    }

    /// <summary>
    /// XA事务模板类，提供编程式事务支持
    /// </summary>
    public class XaTransactionTemplate
    {
        private readonly ILogger<XaTransactionTemplate> _logger;
        private readonly IXaTransactionManager _xaTransactionManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="xaTransactionManager">XA事务管理器</param>
        public XaTransactionTemplate(
            ILogger<XaTransactionTemplate> logger,
            IXaTransactionManager xaTransactionManager)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _xaTransactionManager = xaTransactionManager ?? throw new ArgumentNullException(nameof(xaTransactionManager));
        }

        /// <summary>
        /// 执行XA事务
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="action">事务操作</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>操作结果</returns>
        public async Task<T> ExecuteAsync<T>(Func<Task<T>> action, int timeout = TransactionConstants.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(action));

            _logger.LogInformation("开始执行XA事务模板");
            
            // 检查是否已经有全局事务
            var xid = RootContext.GetXid();
            if (!string.IsNullOrEmpty(xid))
            {
                _logger.LogInformation("已存在全局事务，直接执行操作: xid={xid}", xid);
                return await action();
            }

            GlobalTransactionContext transactionContext = null;
            try
            {
                // 开始XA全局事务
                xid = await _xaTransactionManager.BeginAsync(timeout);

                _logger.LogInformation("XA全局事务已开始: xid={xid}", xid);
                
                // 绑定XID到上下文
                RootContext.Bind(xid);
                
                // 执行操作
                var result = await action();
                
                // 提交XA事务
                var commitResult = await _xaTransactionManager.CommitAsync(xid);
                
                if (commitResult)
                {
                    _logger.LogInformation("XA全局事务已提交: xid={xid}", xid);
                }
                else
                {
                    _logger.LogWarning("XA全局事务提交失败: xid={xid}", xid);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "XA事务模板执行异常: xid={xid}", xid);
                
                if (!string.IsNullOrEmpty(xid))
                {
                    try
                    {
                        // 回滚XA事务
                        var rollbackResult = await _xaTransactionManager.RollbackAsync(xid);
                        
                        if (rollbackResult)
                        {
                            _logger.LogInformation("XA全局事务已回滚: xid={xid}", xid);
                        }
                        else
                        {
                            _logger.LogWarning("XA全局事务回滚失败: xid={xid}", xid);
                        }
                    }
                    catch (Exception rollbackEx)
                    {
                        _logger.LogError(rollbackEx, "XA事务模板回滚异常: xid={xid}", xid);
                    }
                }
                
                throw;
            }
            finally
            {
                // 清理上下文
                RootContext.Unbind();
            }
        }

        /// <summary>
        /// 执行XA事务（无返回值）
        /// </summary>
        /// <param name="action">事务操作</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>任务</returns>
        public async Task ExecuteAsync(Func<Task> action, int timeout = TransactionConstants.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT)
        {
            await ExecuteAsync<object>(async () =>
            {
                await action();
                return null;
            }, timeout);
        }
    }

    /// <summary>
    /// XA数据源代理工厂
    /// </summary>
    public interface IXaDataSourceProxyFactory
    {
        /// <summary>
        /// 创建XA连接
        /// </summary>
        /// <param name="connection">原始连接</param>
        /// <param name="xid">全局事务ID</param>
        /// <returns>XA连接</returns>
        DbConnection CreateXaConnection(DbConnection connection, string xid);
    }

    /// <summary>
    /// 默认XA数据源代理工厂实现
    /// </summary>
    public class DefaultXaDataSourceProxyFactory : IXaDataSourceProxyFactory
    {
        private readonly IXaTransactionManager _xaTransactionManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="xaTransactionManager">XA事务管理器</param>
        public DefaultXaDataSourceProxyFactory(IXaTransactionManager xaTransactionManager)
        {
            _xaTransactionManager = xaTransactionManager ?? throw new ArgumentNullException(nameof(xaTransactionManager));
        }

        /// <summary>
        /// 创建XA连接
        /// </summary>
        /// <param name="connection">原始连接</param>
        /// <param name="xid">全局事务ID</param>
        /// <returns>XA连接</returns>
        public DbConnection CreateXaConnection(DbConnection connection, string xid)
        {
            return _xaTransactionManager.CreateXaConnection(connection, xid);
        }
    }
}